package org.xxpay.pay.channel.xkpay;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import org.xxpay.common.bean.result.PayException;
import org.xxpay.common.exception.PayErrorException;
import org.xxpay.common.http.HttpRequestTemplate;
import org.xxpay.common.util.DateUtils;
import org.xxpay.common.util.Util;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.common.util.str.StringUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.JsonUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;

import java.util.Date;
import java.util.Map;

@Service
public class XkPaymentService extends BasePayment {

    private final static String logPrefix = "【KX】";

    private final static String QUICK_ORDER_CREATE_URL = "/createXKPay";

    private final static String ORDER_QUERY_URL = "/queryorder";

    @Override
    public String getChannelName() {
        return XkConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        switch (channelId) {
            case XkConfig.CHANNEL_NAME_XK_QUICK:
                return createQuickOrder(payOrder);
            case XkConfig.CHANNEL_NAME_JD_QR:
                return createQuickOrder(payOrder);
            case XkConfig.CHANNEL_NAME_UNION_QR:
                return createQuickOrder(payOrder);
            default:
                return buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
        }
    }

    @Override
    public JSONObject query(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        switch (channelId) {
            case XkConfig.CHANNEL_NAME_XK_QUICK:
                return doOrderQuickQuery(payOrder);
            default:
                return buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
        }
    }

    private JSONObject doOrderQuickQuery(PayOrder payOrder) {
        XkConfig xkConfig = new XkConfig(getPayParam(payOrder));
        Map<String, Object> paramMap = Maps.newHashMap();
        buildQueryParam(paramMap, payOrder, xkConfig);
        _log.info("{}查询订单下单请求参数：{}", logPrefix, JSONObject.toJSONString(paramMap));
        String sign = getQueryOrderSign(paramMap, xkConfig);
        paramMap.put("sign", sign);
        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(xkConfig.getRequestUrl(), ORDER_QUERY_URL), paramMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        JSONObject retObj =  new JSONObject();
        _log.info("{}请求响应参数：{}", logPrefix, JsonUtil.object2Json(resObject));
        String returnCode = resObject.getString("return_code");
        if (StringUtils.equals(returnCode, "0")){
            retObj.put("status", 1); // 支付中
        }else if (StringUtils.equals(returnCode, "1")) {
            retObj.put("status", 2); // 已支付
            retObj.put("channelOrderNo", resObject.getString("ordernumber"));
            retObj.put("channelObj", resObject);
        }else {
            retObj.put("status", 4); // 未支付
            retObj.put("channelObj", resObject);
        }
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_SUCCESS);
        return retObj;
    }

    private JSONObject createQuickOrder(PayOrder payOrder) {
        XkConfig xkConfig = new XkConfig(getPayParam(payOrder));
        Map<String, Object> paramMap = Maps.newHashMap();
        buildQuickOrderParam(paramMap, payOrder, xkConfig);
        String sign = getCreateOrderSign(paramMap, xkConfig);
        paramMap.put("sign", sign);
        _log.info("{}订单下单请求参数：{}", logPrefix, JSONObject.toJSONString(paramMap));

        rpcCommonService.rpcPayOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null);

        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        String origin = requestTemplate.postForObject(getReqUrl(xkConfig.getRequestUrl(), QUICK_ORDER_CREATE_URL), paramMap, String.class);
        JSONObject resObject = JsonUtil.getObjectFromJson(origin, JSONObject.class);
        _log.info("{}请求响应参数：{}", logPrefix, JsonUtil.object2Json(resObject));
        JSONObject retObj = new JSONObject();
        String returnCode = resObject.getString("return_code");
        if (StringUtils.equals(returnCode, "1")){
            retObj.put("status", 2); // 已支付
            retObj.put("channelOrderNo", resObject.getString("out_trade_no"));
            String payUrl = resObject.getString("pay_url");
            return buildPayResultOfCodeURL(retObj, payOrder,payUrl);
        }else {
            retObj.put("status", 3); // 失败
            throw  new PayErrorException(new PayException("Invalid Arguments", "XK下单失败"));
        }
    }

    private void buildQuickOrderParam(Map<String, Object> params, PayOrder payOrder, XkConfig xkConfig) {
        params.put("merchant_no",xkConfig.getMchId());
        params.put("pay_num", payOrder.getPayOrderId());
        params.put("total_fee", Util.conversionYuanAmount(payOrder.getAmount()));
        params.put("pay_method", 1);
        params.put("clientip", payOrder.getClientIp());
        params.put("return_url", payOrder.getReturnUrl());
        params.put("notify_url", payConfig.getNotifyUrl(getChannelName()));
    }

    private void buildQueryParam(Map<String, Object> params, PayOrder payOrder, XkConfig xkConfig) {
        params.put("merchant_no",xkConfig.getMchId());
        params.put("pay_num", payOrder.getPayOrderId());
        params.put("pay_way", 4);
    }

    private String getCreateOrderSign(Map<String, Object> params, XkConfig xkConfig) {
        String text = String.valueOf(params.get("merchant_no"))
                +params.get("pay_num")
                +params.get("total_fee")
                +DateUtils.YYYYMMDD.format(new Date());
        return SignUtils.MD5.createSign(text, xkConfig.getPrivateKey(), SignUtils.CHARSET_UTF8).toUpperCase();
    }

    private String getQueryOrderSign(Map<String, Object> params, XkConfig xkConfig) {
        String text = String.valueOf(params.get("merchant_no"))
                +params.get("pay_num")
                +DateUtils.YYYYMMDD.format(new Date());
        return SignUtils.MD5.createSign(text, xkConfig.getPrivateKey(), SignUtils.CHARSET_UTF8).toUpperCase();
    }

}
